from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
from fastapi.middleware import Middleware
from fastapi.middleware.cors import CORSMiddleware
from fastapi_limiter import FastAPILimiter
from contextlib import asynccontextmanager

from domain import api_v1_router
from utils import (
    default_thread_pool
)
from common.log import init_log, log
from common.redis import redis_client
from common.exception.exception_handlers import register_exception
from middleware .access_middleware import AccessMiddleware
from utils.health_check import http_limit_callback

from config.base import get_settings

settings = get_settings()

def register_middleware(app: FastAPI) -> None:
    # 跨域
    if settings.app.MIDDLEWARE_CORS:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=settings.app.ALLOWED_CORS_ORIGINS,
            allow_credentials=settings.app.ALLOWED_CORS_CREDENTIALS,
            allow_methods=settings.app.ALLOWED_CORS_HEADERS,
            allow_headers=settings.app.ALLOWED_CORS_HEADERS,
        )
    # 接口访问日志
    if settings.app.MIDDLEWARE_ACCESS:
        app.add_middleware(AccessMiddleware)


def register_db(app: FastAPI, db_url=None):
    pass


def register_routers(app: FastAPI, prefix: str = "/api"):
    app.include_router(api_v1_router, prefix=prefix)
    

@asynccontextmanager
async def lifespan(app: FastAPI):
    if settings.log.FORMAT:
        await init_log()
    log.info("程序启动成功")
    if settings.redis.ENABLED:
        '''如果 ENABLE_REDIS true 初始化 redis'''
        await redis_client.init_redis()
    if settings.app.ENABLE_LIMITER and settings.redis.ENABLED:
        '''启用 limiter，初始化 limiter'''
        await FastAPILimiter.init(
            redis=redis_client, prefix=settings.app.REQUEST_LIMITER_REDIS_PREFIX, http_callback=http_limit_callback
        )
        
    log.info(f"环境：{settings.app.ENV}")
    yield
    await default_thread_pool.shutdown()
    if settings.app.ENABLE_LIMITER and settings.redis.ENABLED:
        '''关闭 limiter'''
        await FastAPILimiter.close()
    if settings.redis.ENABLED:
        '''关闭 redis'''
        await redis_client.close()
    log.info("程序关闭")
    
    
def create_app(lifespan) -> FastAPI:
    app = FastAPI(
        title=settings.app.TITLE,
        description=settings.app.DESCRIPTION,
        version=settings.app.VERSION,
        openapi_url="/openapi.json",
        lifespan=lifespan,
        default_response_class=ORJSONResponse
    )
    register_exception(app)
    register_routers(app, prefix="/api")
    register_middleware(app)
    return app

